package team.seekers.catering.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import team.seekers.catering.common.enums.DRIsEnum;
import team.seekers.catering.entity.dataobject.Ingredient;
import team.seekers.catering.entity.params.add.FoodAddPA;
import team.seekers.catering.entity.params.add.FoodContentListPA;
import team.seekers.catering.entity.params.add.FoodUpdatePA;
import team.seekers.catering.entity.params.update.IngredientUpdatePA;
import team.seekers.catering.entity.temp.NutrimentListDTO;
import team.seekers.catering.entity.vo.info.FoodInfoVO;
import team.seekers.catering.entity.vo.info.IngredientInfoVO;
import team.seekers.catering.entity.vo.list.IngredientListVO;
import team.seekers.catering.mapper.IngredientMapper;
import team.seekers.catering.service.IngredientService;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 食材表 服务实现类
 * </p>
 *
 * @author hbc
 * @since 2022-01-21
 */
@Service
public class IngredientServiceImpl extends ServiceImpl<IngredientMapper, Ingredient> implements IngredientService {

    @Override
    public Map<String, Object> adminPageOrder(long current, long limit, QueryWrapper<Ingredient> wrapper) {
        Page<Ingredient> page = new Page<>(current,limit);
        page(page,wrapper);
        Long total = page.getTotal();
        if(page.getRecords() == null){
            return null;
        }
        System.out.println("获取的记录是"+page.getRecords());

        List<IngredientListVO> list = new ArrayList<>();
        for (Ingredient record : page.getRecords()) {
            IngredientListVO vo = new IngredientListVO();
            BeanUtils.copyProperties(record,vo);
            list.add(vo);
        }
        Map<String,Object> map = new HashMap<>();
        map.put("total",total);
        map.put("rows",list);
        return map;
    }

    @Override
    public void setParamFromList(FoodAddPA foodAddPA) {
        // 单位换算
        // 百克换克
        BigDecimal hundred = new BigDecimal("100.0");


        BigDecimal kalSum = new BigDecimal("0.0");;// 总能量
        BigDecimal amountSum  = new BigDecimal("0.0");;// 总质量
        BigDecimal pro = new BigDecimal("0.0");// 蛋白质的总质量
        BigDecimal fat = new BigDecimal("0.0");// 脂肪的总质量
        BigDecimal cho = new BigDecimal("0.0");// 碳水的总质量
        BigDecimal fibtg = new BigDecimal("0.0");// 膳食纤维的总质量

        BigDecimal naSum = new BigDecimal("0.0");// 蛋白质的总质量
        BigDecimal kSum = new BigDecimal("0.0");// 脂肪的总质量
        BigDecimal caSum = new BigDecimal("0.0");// 碳水的总质量
        BigDecimal vitc = new BigDecimal("0.0");// 膳食纤维的总质量



        BigDecimal price = new BigDecimal("0.0");
        for (FoodContentListPA foodContentListPA : foodAddPA.getContentList()) {
            Ingredient ingredient = getById(foodContentListPA.getId());
            BigDecimal amount = new BigDecimal(foodContentListPA.getAmount());
            BigDecimal kal = new BigDecimal(ingredient.getNcEnergy());
            BigDecimal na = new BigDecimal(ingredient.getNcNa());
            BigDecimal k = new BigDecimal(ingredient.getNcK());
            BigDecimal ca = new BigDecimal(ingredient.getNcCa());


            amountSum = amountSum.add(ingredient.getNcRemain().multiply(amount));
            kalSum = kalSum.add(kal.divide(hundred, 2, BigDecimal.ROUND_HALF_DOWN).multiply(amount));

            pro = pro.add(ingredient.getNcPro().divide(hundred, 2, BigDecimal.ROUND_HALF_DOWN).multiply(amount));
            fat = fat.add(ingredient.getNcFat().divide(hundred, 2, BigDecimal.ROUND_HALF_DOWN).multiply(amount));
            cho = cho.add(ingredient.getNcCho().divide(hundred, 2, BigDecimal.ROUND_HALF_DOWN).multiply(amount));
            fibtg = fibtg.add(ingredient.getNcFibtg().divide(hundred, 2, BigDecimal.ROUND_HALF_DOWN).multiply(amount));

            naSum = naSum.add(na.divide(hundred, 2, BigDecimal.ROUND_HALF_DOWN).multiply(amount));
            kSum = kSum.add(k.divide(hundred, 2, BigDecimal.ROUND_HALF_DOWN).multiply(amount));
            caSum = caSum.add(ca.divide(hundred, 2, BigDecimal.ROUND_HALF_DOWN).multiply(amount));
            vitc = vitc.add(ingredient.getNcVitc().divide(hundred, 2, BigDecimal.ROUND_HALF_DOWN).multiply(amount));



            price = price.add(ingredient.getNcPrice().multiply(new BigDecimal(foodContentListPA.getAmount())));
        }
        // 含量
        // 总质量（单位g）
        foodAddPA.setAmount(amountSum.intValue());
        // 总能量（单位kal）
        foodAddPA.setKal(kalSum.intValue());
        // 总成本价
        foodAddPA.setPrice(price);

        // 百克含量
        BigDecimal proPerHun =pro.divide(amountSum, 2, BigDecimal.ROUND_HALF_DOWN).multiply(hundred);
        BigDecimal fatPerHun = fat.divide(amountSum, 2, BigDecimal.ROUND_HALF_DOWN).multiply(hundred);
        BigDecimal choPerHun = cho.divide(amountSum, 2, BigDecimal.ROUND_HALF_DOWN).multiply(hundred);
        BigDecimal fibtgPerHun = fibtg.divide(amountSum, 2, BigDecimal.ROUND_HALF_DOWN).multiply(hundred);

        BigDecimal naPerHun = naSum.divide(amountSum, 2, BigDecimal.ROUND_HALF_DOWN).multiply(hundred);
        BigDecimal kPerHun = kSum.divide(amountSum, 2, BigDecimal.ROUND_HALF_DOWN).multiply(hundred);
        BigDecimal caPerHun = caSum.divide(amountSum, 2, BigDecimal.ROUND_HALF_DOWN).multiply(hundred);
        BigDecimal vitcPerHun = vitc.divide(amountSum, 2, BigDecimal.ROUND_HALF_DOWN).multiply(hundred);

        // 能量密度
        BigDecimal kalPerHun = kalSum.divide(amountSum, 2, BigDecimal.ROUND_HALF_DOWN).multiply(hundred);
        foodAddPA.setEd(kalPerHun);

        // 供能比计算
        BigDecimal allEr = pro.multiply(new BigDecimal("4.0")).add(
                fat.multiply(new BigDecimal("9.0")).add(
                        cho.multiply(new BigDecimal("4.0"))
                )
        );
        BigDecimal proEr = pro.multiply(new BigDecimal("4.0")).divide(allEr, 2, BigDecimal.ROUND_HALF_DOWN);
        BigDecimal fatEr = fat.multiply(new BigDecimal("9.0")).divide(allEr, 2, BigDecimal.ROUND_HALF_DOWN);
        BigDecimal choEr = cho.multiply(new BigDecimal("4.0")).divide(allEr, 2, BigDecimal.ROUND_HALF_DOWN);
        foodAddPA.setProEr(proEr);
        foodAddPA.setFatEr(fatEr);
        foodAddPA.setChoEr(choEr);

        double proPow = Math.pow(proPerHun.doubleValue(), 0.7);
        BigDecimal proPerHunPow = new BigDecimal(proPow);
        // 饱腹感指数计算
        BigDecimal satietyIndex = new BigDecimal("41.7").divide(proPerHunPow, 2, BigDecimal.ROUND_HALF_DOWN).add(
                new BigDecimal("0.05").multiply(fatPerHun).add(
                        new BigDecimal("0.000617").multiply(choPerHun.pow(3)).subtract(
                                new BigDecimal("0.00000725").multiply(fibtgPerHun.pow(3)).add(new BigDecimal("0.617"))
                        )
                )
        );
        foodAddPA.setSatietyIndex(satietyIndex);

        // 营养素参考值计算（能量、蛋白质、脂肪、碳水化合物、膳食纤维、钠、钾、钙、VC）
        ArrayList<NutrimentListDTO> foodContentDTOS = new ArrayList<>();
        // 能量
        foodContentDTOS.add(
                new NutrimentListDTO(DRIsEnum.KAL.getValue(),kalPerHun.doubleValue(),kalPerHun.divide(
                        new BigDecimal(DRIsEnum.KAL.getAmount()), 2, BigDecimal.ROUND_HALF_DOWN).toString()));
        // 蛋白质
        foodContentDTOS.add(
                new NutrimentListDTO(DRIsEnum.PRO.getValue(),proPerHun.doubleValue(),proPerHun.divide(
                        new BigDecimal(DRIsEnum.PRO.getAmount()), 2, BigDecimal.ROUND_HALF_DOWN).toString()));
        // 脂肪
        foodContentDTOS.add(
                new NutrimentListDTO(DRIsEnum.FAT.getValue(),fatPerHun.doubleValue(),fatPerHun.divide(
                        new BigDecimal(DRIsEnum.FAT.getAmount()), 2, BigDecimal.ROUND_HALF_DOWN).toString()));
        // 碳水化合物
        foodContentDTOS.add(
                new NutrimentListDTO(DRIsEnum.CHO.getValue(),choPerHun.doubleValue(),choPerHun.divide(
                        new BigDecimal(DRIsEnum.CHO.getAmount()), 2, BigDecimal.ROUND_HALF_DOWN).toString()));
        // 膳食纤维
        foodContentDTOS.add(
                new NutrimentListDTO(DRIsEnum.FIBTG.getValue(),fibtgPerHun.doubleValue(),fibtgPerHun.divide(
                        new BigDecimal(DRIsEnum.FIBTG.getAmount()), 2, BigDecimal.ROUND_HALF_DOWN).toString()));
        // 钠
        foodContentDTOS.add(
                new NutrimentListDTO(DRIsEnum.NA.getValue(),naPerHun.doubleValue(),naPerHun.divide(
                        new BigDecimal(DRIsEnum.NA.getAmount()), 2, BigDecimal.ROUND_HALF_DOWN).toString()));
        // 钾
        foodContentDTOS.add(
                new NutrimentListDTO(DRIsEnum.K.getValue(),kPerHun.doubleValue(),kPerHun.divide(
                        new BigDecimal(DRIsEnum.K.getAmount()), 2, BigDecimal.ROUND_HALF_DOWN).toString()));
        // 钙
        foodContentDTOS.add(
                new NutrimentListDTO(DRIsEnum.CA.getValue(),caPerHun.doubleValue(),caPerHun.divide(
                        new BigDecimal(DRIsEnum.CA.getAmount()), 2, BigDecimal.ROUND_HALF_DOWN).toString()));
        // VC
        foodContentDTOS.add(
                new NutrimentListDTO(DRIsEnum.VITC.getValue(),vitcPerHun.doubleValue(),vitcPerHun.divide(
                        new BigDecimal(DRIsEnum.VITC.getAmount()), 2, BigDecimal.ROUND_HALF_DOWN).toString()));

        foodAddPA.setNd(foodContentDTOS);
    }

    @Override
    public void setParamFromList(FoodUpdatePA foodAddPA) {
        // 单位换算
        // 百克换克
        BigDecimal hundred = new BigDecimal("100.0");


        BigDecimal kalSum = new BigDecimal("0.0");;// 总能量
        BigDecimal amountSum  = new BigDecimal("0.0");;// 总质量
        BigDecimal pro = new BigDecimal("0.0");// 蛋白质的总质量
        BigDecimal fat = new BigDecimal("0.0");// 脂肪的总质量
        BigDecimal cho = new BigDecimal("0.0");// 碳水的总质量
        BigDecimal fibtg = new BigDecimal("0.0");// 膳食纤维的总质量

        BigDecimal naSum = new BigDecimal("0.0");// 蛋白质的总质量
        BigDecimal kSum = new BigDecimal("0.0");// 脂肪的总质量
        BigDecimal caSum = new BigDecimal("0.0");// 碳水的总质量
        BigDecimal vitc = new BigDecimal("0.0");// 膳食纤维的总质量



        BigDecimal price = new BigDecimal("0.0");
        for (FoodContentListPA foodContentListPA : foodAddPA.getContentList()) {
            Ingredient ingredient = getById(foodContentListPA.getId());
            BigDecimal amount = new BigDecimal(foodContentListPA.getAmount());
            BigDecimal kal = new BigDecimal(ingredient.getNcEnergy());
            BigDecimal na = new BigDecimal(ingredient.getNcNa());
            BigDecimal k = new BigDecimal(ingredient.getNcK());
            BigDecimal ca = new BigDecimal(ingredient.getNcCa());


            amountSum = amountSum.add(ingredient.getNcRemain().multiply(amount));
            kalSum = kalSum.add(kal.divide(hundred, 2, BigDecimal.ROUND_HALF_DOWN).multiply(amount));

            pro = pro.add(ingredient.getNcPro().divide(hundred, 2, BigDecimal.ROUND_HALF_DOWN).multiply(amount));
            fat = fat.add(ingredient.getNcFat().divide(hundred, 2, BigDecimal.ROUND_HALF_DOWN).multiply(amount));
            cho = cho.add(ingredient.getNcCho().divide(hundred, 2, BigDecimal.ROUND_HALF_DOWN).multiply(amount));
            fibtg = fibtg.add(ingredient.getNcFibtg().divide(hundred, 2, BigDecimal.ROUND_HALF_DOWN).multiply(amount));

            naSum = naSum.add(na.divide(hundred, 2, BigDecimal.ROUND_HALF_DOWN).multiply(amount));
            kSum = kSum.add(k.divide(hundred, 2, BigDecimal.ROUND_HALF_DOWN).multiply(amount));
            caSum = caSum.add(ca.divide(hundred, 2, BigDecimal.ROUND_HALF_DOWN).multiply(amount));
            vitc = vitc.add(ingredient.getNcVitc().divide(hundred, 2, BigDecimal.ROUND_HALF_DOWN).multiply(amount));



            price = price.add(ingredient.getNcPrice().multiply(new BigDecimal(foodContentListPA.getAmount())));
        }
        // 含量
        // 总质量（单位g）
        foodAddPA.setAmount(amountSum.intValue());
        // 总能量（单位kal）
        foodAddPA.setKal(kalSum.intValue());
        // 总成本价
        foodAddPA.setPrice(price);

        // 百克含量
        BigDecimal proPerHun =pro.divide(amountSum, 2, BigDecimal.ROUND_HALF_DOWN).multiply(hundred);
        BigDecimal fatPerHun = fat.divide(amountSum, 2, BigDecimal.ROUND_HALF_DOWN).multiply(hundred);
        BigDecimal choPerHun = cho.divide(amountSum, 2, BigDecimal.ROUND_HALF_DOWN).multiply(hundred);
        BigDecimal fibtgPerHun = fibtg.divide(amountSum, 2, BigDecimal.ROUND_HALF_DOWN).multiply(hundred);

        BigDecimal naPerHun = naSum.divide(amountSum, 2, BigDecimal.ROUND_HALF_DOWN).multiply(hundred);
        BigDecimal kPerHun = kSum.divide(amountSum, 2, BigDecimal.ROUND_HALF_DOWN).multiply(hundred);
        BigDecimal caPerHun = caSum.divide(amountSum, 2, BigDecimal.ROUND_HALF_DOWN).multiply(hundred);
        BigDecimal vitcPerHun = vitc.divide(amountSum, 2, BigDecimal.ROUND_HALF_DOWN).multiply(hundred);

        // 能量密度
        BigDecimal kalPerHun = kalSum.divide(amountSum, 2, BigDecimal.ROUND_HALF_DOWN).multiply(hundred);
        foodAddPA.setEd(kalPerHun);

        // 供能比计算
        BigDecimal allEr = pro.multiply(new BigDecimal("4.0")).add(
                fat.multiply(new BigDecimal("9.0")).add(
                        cho.multiply(new BigDecimal("4.0"))
                )
        );
        BigDecimal proEr = pro.multiply(new BigDecimal("4.0")).divide(allEr, 2, BigDecimal.ROUND_HALF_DOWN);
        BigDecimal fatEr = fat.multiply(new BigDecimal("9.0")).divide(allEr, 2, BigDecimal.ROUND_HALF_DOWN);
        BigDecimal choEr = cho.multiply(new BigDecimal("4.0")).divide(allEr, 2, BigDecimal.ROUND_HALF_DOWN);
        foodAddPA.setProEr(proEr);
        foodAddPA.setFatEr(fatEr);
        foodAddPA.setChoEr(choEr);

        double proPow = Math.pow(proPerHun.doubleValue(), 0.7);
        BigDecimal proPerHunPow = new BigDecimal(proPow);
        // 饱腹感指数计算
        BigDecimal satietyIndex = new BigDecimal("41.7").divide(proPerHunPow, 2, BigDecimal.ROUND_HALF_DOWN).add(
                new BigDecimal("0.05").multiply(fatPerHun).add(
                        new BigDecimal("0.000617").multiply(choPerHun.pow(3)).subtract(
                                new BigDecimal("0.00000725").multiply(fibtgPerHun.pow(3)).add(new BigDecimal("0.617"))
                        )
                )
        );
        foodAddPA.setSatietyIndex(satietyIndex);

        // 营养素参考值计算（能量、蛋白质、脂肪、碳水化合物、膳食纤维、钠、钾、钙、VC）
        ArrayList<NutrimentListDTO> foodContentDTOS = new ArrayList<>();
        // 能量
        foodContentDTOS.add(
                new NutrimentListDTO(DRIsEnum.KAL.getValue(),kalPerHun.doubleValue(),kalPerHun.divide(
                        new BigDecimal(DRIsEnum.KAL.getAmount()), 2, BigDecimal.ROUND_HALF_DOWN).toString()));
        // 蛋白质
        foodContentDTOS.add(
                new NutrimentListDTO(DRIsEnum.PRO.getValue(),proPerHun.doubleValue(),proPerHun.divide(
                        new BigDecimal(DRIsEnum.PRO.getAmount()), 2, BigDecimal.ROUND_HALF_DOWN).toString()));
        // 脂肪
        foodContentDTOS.add(
                new NutrimentListDTO(DRIsEnum.FAT.getValue(),fatPerHun.doubleValue(),fatPerHun.divide(
                        new BigDecimal(DRIsEnum.FAT.getAmount()), 2, BigDecimal.ROUND_HALF_DOWN).toString()));
        // 碳水化合物
        foodContentDTOS.add(
                new NutrimentListDTO(DRIsEnum.CHO.getValue(),choPerHun.doubleValue(),choPerHun.divide(
                        new BigDecimal(DRIsEnum.CHO.getAmount()), 2, BigDecimal.ROUND_HALF_DOWN).toString()));
        // 膳食纤维
        foodContentDTOS.add(
                new NutrimentListDTO(DRIsEnum.FIBTG.getValue(),fibtgPerHun.doubleValue(),fibtgPerHun.divide(
                        new BigDecimal(DRIsEnum.FIBTG.getAmount()), 2, BigDecimal.ROUND_HALF_DOWN).toString()));
        // 钠
        foodContentDTOS.add(
                new NutrimentListDTO(DRIsEnum.NA.getValue(),naPerHun.doubleValue(),naPerHun.divide(
                        new BigDecimal(DRIsEnum.NA.getAmount()), 2, BigDecimal.ROUND_HALF_DOWN).toString()));
        // 钾
        foodContentDTOS.add(
                new NutrimentListDTO(DRIsEnum.K.getValue(),kPerHun.doubleValue(),kPerHun.divide(
                        new BigDecimal(DRIsEnum.K.getAmount()), 2, BigDecimal.ROUND_HALF_DOWN).toString()));
        // 钙
        foodContentDTOS.add(
                new NutrimentListDTO(DRIsEnum.CA.getValue(),caPerHun.doubleValue(),caPerHun.divide(
                        new BigDecimal(DRIsEnum.CA.getAmount()), 2, BigDecimal.ROUND_HALF_DOWN).toString()));
        // VC
        foodContentDTOS.add(
                new NutrimentListDTO(DRIsEnum.VITC.getValue(),vitcPerHun.doubleValue(),vitcPerHun.divide(
                        new BigDecimal(DRIsEnum.VITC.getAmount()), 2, BigDecimal.ROUND_HALF_DOWN).toString()));

        foodAddPA.setNd(foodContentDTOS);
    }

    @Override
    public IngredientInfoVO get(String id) {
        Ingredient ingredient = getById(id);
        IngredientInfoVO ingredientInfoVO = new IngredientInfoVO();
        BeanUtils.copyProperties(ingredient,ingredientInfoVO);
        return ingredientInfoVO;
    }

    @Override
    public Long update(IngredientUpdatePA ingredientUpdatePA) {
        Ingredient ingredient = new Ingredient();
        BeanUtils.copyProperties(ingredientUpdatePA,ingredient);
        updateById(ingredient);
        return ingredient.getNcId();
    }
}
